An agent that remembers its own failures so it never makes the same mistake twice.
Solve Track 01 · Memory. AI agents get stuck in loops: same error, same response, same failure, repeat. Agent-Scars breaks that cycle by tracking failures and injecting a guard block into the prompt on the next turn, forcing the agent to acknowledge and fix the error instead of repeating it. Extracted from 18 months of production Agentic OS.
Most AI agents loop because they have no memory of failure. An agent that tries the same syntactically invalid code three times in a row isn't dumb: it has forgotten the first two tries. The context window resets, the previous error scrolls out of view, and the agent confidently produces the exact same broken output.
In production Agentic OS, this manifested as the code-generation agent producing identical syntax errors across 3 to 5 consecutive turns. The fix wasn't "use a better model" - it was giving the agent persistent failure memory so it could see what it already tried and failed at.
The system uses a three-beat pattern: Record → Detect → Guard. Each beat is a single function call.
scar.recordIncident(type, agent, provider, statusCode, message). This logs the failure to SQLite (with full ACID guarantees) or to a JSON fallback file if better-sqlite3 isn't installed. Each incident records: the error type, which agent failed, which LLM provider was used, the HTTP status code, and the raw error message. Incidents are keyed by workspace and project, enabling multi-tenant tracking.
scar.detectFailurePatterns(scars). This scans recent failures against a bank of 8 built-in regex patterns (syntax errors, ESM/CJS conflicts, rate limits, path traversal, etc.) and counts how many times each pattern has fired. If a pattern repeats 2 or more times, it's flagged with a specific human-readable fix instruction. You can extend the pattern bank by adding entries to the knownFixes array in the constructor.
scar.injectRepeatGuard(prompt, scars). If patterns were detected, a structured warning block is prepended to the agent's system prompt. The guard block looks like a formatted instruction section that the LLM reads before generating its response. It explicitly lists each repeated error, how many times it occurred, and the specific fix instruction. The agent reads this, recognizes the pattern, and changes its approach.
### !!! REPEAT FAILURE GUARD - DO NOT REPEAT THESE ERRORS !!!
The following errors have occurred MULTIPLE times in this session.
Prioritize fixing them:
▶ Pattern: SYNTAX COMPLIANCE ERROR (Failed 2 times)
Fix: Output must be valid syntax. Verify braces, brackets,
parentheses, and commas. Never truncate output mid-block.
▶ Pattern: ESM IMPORT IN COMMONJS (Failed 2 times)
Fix: File runs in CommonJS. Use require() instead of import.
### !!! END REPEAT FAILURE GUARD !!!
The agent reads this before it sees the user's actual request. It's equivalent to a senior engineer tapping the junior on the shoulder and saying "you already tried that twice and it broke both times - here's what to do differently."
SCAR ships with regex matchers for the 8 most common agent mistakes in production:
import in a file that runs as CommonJS. Fix: use require().eval() and exec() are forbidden in the codebase... or absolute paths allowed in file operations.
If better-sqlite3 is installed, incidents go to ./data/scars.db with full ACID guarantees, WAL mode, and indexed queries. If the native module isn't available (e.g. in a sandboxed CI environment), SCAR automatically falls back to ./data/incidents.json - same API, same behavior, just file-based persistence. You'll see a single log line:
[SCAR] SQLite unavailable. Falling back to JSON incident logs.
git clone https://github.com/shubham0086/Agent-Scars cd Agent-Scars npm install # See the guard block appear after the 3rd failure npm run demo:guard # See incidents persist across separate sessions npm run demo:persist
No API key needed. Runs fully offline in mock mode.
import { SCAR } from 'agent-scars';
// 1. Create instance (multi-tenant by workspace + project)
const scar = new SCAR('my-workspace', 'my-project');
// 2. Record a failure
scar.recordIncident('syntax_error', 'coder', 'openai', 400, 'Unexpected token }');
// 3. Get recent failures
const scars = scar.getRecentScars(10);
// 4. Detect patterns
const patterns = scar.detectFailurePatterns(scars);
// → [{ pattern: 'SYNTAX ERROR', count: 2, hint: '...' }]
// 5. Inject guard into prompt
const guarded = scar.injectRepeatGuard(originalPrompt, scars);
// → prepends warning block if patterns found
Agent-Scars is the memory + consistency proof from the autonomy ladder. It implements Pattern 03 (Reality-First Memory) and Pattern 07 (Anti-Drift) from Agentic Patterns. The full production engine that uses SCAR in its pipeline is AgentKernel. For cross-session solution memory (the positive counterpart to failure memory), see Agent-Recall.
This is pattern detection via regex, not semantic understanding. It catches the 8 most common production failures reliably. It won't catch novel error categories unless you add them to knownFixes. The v2 roadmap includes LLM-assisted pattern extraction for unknown error types, but the regex approach has been production-stable for 18 months and handles the vast majority of real cases.